#include "Process.h"

Process::Process(LogFile* logFile) {
	this->logFile = logFile;
}

string Process::convertToString(int value) {
	stringstream stream;
	stream << value;
	return stream.str();
}

list<int> Process::getProcessIds() {
	return this->processIds;
}

void Process::setParentProcessName(string parentProcessName) {
	this->parentProcessName = parentProcessName;
}

string Process::getParentProcessName() {
	return this->parentProcessName;
}

void Process::start() {
	this->logFile->log(
			"[" + this->getParentProcessName() + "] " +
			"Realizando fork para crear un proceso hijo: " +
			this->getProcessName());

	int processId = fork();

	if (processId == 0) {
		// Proceso Hijo.
		// Ejecuta el codigo especifico del nuevo proceso hijo.

		this->logFile->log(
				"[" + this->getProcessName() + "] " +
				"Proceso hijo iniciado.");

		int returnCode = this->doWork();

		this->logFile->log(
				"[" + this->getProcessName() + "] " +
				"Proceso hijo terminado.");

		this->logFile->log(
				"[" + this->getProcessName() + "] " +
				"Limpiando lista de processIds.");
		this->processIds.clear();

		this->logFile->log("[" + this->getProcessName() + "] Destruyendo handler de señales.");
		SignalHandler::destruir();

		this->logFile->log(
				"[" + this->getProcessName() + "] " +
				"Destruyendo la instancia del log.");
		this->logFile->destroy();

		// Termina el proceso devolviendo el codigo de retorno.
		exit(returnCode);
	}
	else if (processId > 0)
	{
		this->logFile->log(
				"[" + this->getParentProcessName() + "] " +
				"Proceso hijo iniciado con exito: " + this->getProcessName() +
				"(" + Process::convertToString(processId) + ")");

		// Agrego el nuevo proceso hijo a la lista de processIds.
		this->processIds.push_back(processId);
	}
	else {
		this->logFile->log(
				"[" + this->getParentProcessName() + "] " +
				"No se pudo iniciar un nuevo proceso hijo: " + this->getProcessName());
	}
}

void Process::wait() {
	list<int>::iterator it;
	int processId = 0;
	for (it = this->processIds.begin(); it != this->processIds.end(); it++) {
		processId = *it;

		logFile->log(
				"[" + this->getParentProcessName() + "] " +
				"Proceso bloqueado esperando que termine el proceso hijo: " +
				this->getProcessName() + "(" + Process::convertToString(processId) + ")");

		waitpid(processId, NULL, 0);

		logFile->log(
				"[" + this->getParentProcessName() + "] " +
				"Se termino la espera. El proceso hijo termino: " +
				this->getProcessName() + "(" + Process::convertToString(processId) + ")");
	}
}

Process::~Process() {
}
